package web

import (
	"embed"
	"encoding/json"
	"fmt"
	"io/fs"
	"log"
	"net/http"
	"sync"
	"time"
	"uselesscapslock/config"
	"uselesscapslock/platform"

	"context"

	"github.com/gorilla/websocket"
)

//go:embed static
var staticFiles embed.FS

// 配置 websocket
var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许所有来源，因为我们只监听 localhost
	},
}

// Server 表示web服务器
type Server struct {
	port        int
	server      *http.Server
	connections sync.Map
}

// NewServer 创建一个新的web服务器实例
func NewServer(port int) *Server {
	return &Server{
		port: port,
	}
}

// Start 启动web服务器
func (s *Server) Start() error {
	// 设置静态文件服务
	staticFS, err := fs.Sub(staticFiles, "static")
	if err != nil {
		return fmt.Errorf("无法加载静态文件: %v", err)
	}

	// 创建路由复用器
	mux := http.NewServeMux()

	// API路由
	mux.HandleFunc("/api/config", s.handleConfig)

	// WebSocket 路由
	mux.HandleFunc("/ws", s.handleWebSocket)

	// 静态文件服务
	mux.Handle("/", http.FileServer(http.FS(staticFS)))

	// 仅监听localhost
	addr := fmt.Sprintf("127.0.0.1:%d", s.port)
	log.Printf("启动web服务器在: http://%s", addr)

	// 创建 HTTP 服务器
	s.server = &http.Server{
		Addr:    addr,
		Handler: mux,
	}

	// 启动服务器
	return s.server.ListenAndServe()
}

// handleConfig 处理配置API请求
func (s *Server) handleConfig(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "GET":
		// 获取配置
		cfg, err := config.LoadConfig()
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		json.NewEncoder(w).Encode(cfg)

	case "POST":
		// 更新配置
		var newConfig config.Config
		if err := json.NewDecoder(r.Body).Decode(&newConfig); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		if err := config.SaveConfig(&newConfig); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 重新加载键盘管理器配置
		if err := platform.GetKeyboardManager().ReloadConfig(); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `{"status": "success"}`)

	default:
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
	}
}

// WSMessage WebSocket消息结构
type WSMessage struct {
	Type    string      `json:"type"`
	Data    interface{} `json:"data"`
	Success bool        `json:"success"`
	Error   string      `json:"error,omitempty"`
}

// handleWebSocket 处理 WebSocket 连接
func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("WebSocket 升级失败: %v", err)
		return
	}

	// 生成唯一的连接ID
	connID := fmt.Sprintf("%p", conn)
	s.connections.Store(connID, conn)

	// 清理连接
	defer func() {
		conn.Close()
		s.connections.Delete(connID)
		// 不要在这里退出程序，只需要清理连接
		log.Printf("WebSocket 连接已关闭: %s", connID)
	}()

	// 启动心跳
	go s.heartbeat(conn, connID)

	// 保持连接活跃
	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
				log.Printf("WebSocket 错误: %v", err)
			}
			break
		}

		// 处理消息
		var msg WSMessage
		if err := json.Unmarshal(message, &msg); err != nil {
			s.sendError(conn, "无效的消息格式")
			continue
		}

		switch msg.Type {
		case "getAutoStart":
			enabled, err := platform.GetAutoStartStatus()
			if err != nil {
				s.sendError(conn, fmt.Sprintf("获取自启动状态失败: %v", err))
				continue
			}
			s.sendMessage(conn, "autoStartStatus", enabled)

		case "setAutoStart":
			enable, ok := msg.Data.(bool)
			if !ok {
				s.sendError(conn, "无效的参数类型")
				continue
			}
			if err := platform.SetAutoStart(enable); err != nil {
				s.sendError(conn, fmt.Sprintf("设置自启动失败: %v", err))
				continue
			}
			s.sendMessage(conn, "autoStartStatus", enable)

		case "getSettings":
			cfg, err := config.LoadConfig()
			if err != nil {
				s.sendError(conn, fmt.Sprintf("获取设置失败: %v", err))
				continue
			}
			s.sendMessage(conn, "settings", cfg.Settings)

		case "setSettings":
			cfg, err := config.LoadConfig()
			if err != nil {
				s.sendError(conn, fmt.Sprintf("加载配置失败: %v", err))
				continue
			}

			settings, ok := msg.Data.(map[string]interface{})
			if !ok {
				s.sendError(conn, "无效的设置数据")
				continue
			}

			if autoOpen, exists := settings["auto_open_config"]; exists {
				cfg.Settings.AutoOpenConfig = autoOpen.(bool)
			}

			if err := config.SaveConfig(cfg); err != nil {
				s.sendError(conn, fmt.Sprintf("保存设置失败: %v", err))
				continue
			}
			s.sendMessage(conn, "settings", cfg.Settings)
		}
	}
}

// heartbeat 发送心跳包
func (s *Server) heartbeat(conn *websocket.Conn, connID string) {
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
				log.Printf("心跳发送失败: %v", err)
				return
			}
		}
	}
}

// sendMessage 发送WebSocket消息
func (s *Server) sendMessage(conn *websocket.Conn, msgType string, data interface{}) {
	msg := WSMessage{
		Type:    msgType,
		Data:    data,
		Success: true,
	}
	if err := conn.WriteJSON(msg); err != nil {
		log.Printf("发送消息失败: %v", err)
	}
}

// sendError 发送错误消息
func (s *Server) sendError(conn *websocket.Conn, errMsg string) {
	msg := WSMessage{
		Type:    "error",
		Success: false,
		Error:   errMsg,
	}
	if err := conn.WriteJSON(msg); err != nil {
		log.Printf("发送错误消息失败: %v", err)
	}
}

func (s *Server) Stop() error {
	if s.server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()

		// 关闭所有 WebSocket 连接
		s.connections.Range(func(key, value interface{}) bool {
			if conn, ok := value.(*websocket.Conn); ok {
				conn.Close()
			}
			return true
		})

		return s.server.Shutdown(ctx)
	}
	return nil
}
